package com.summer.campussct.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.bean.copier.CopyOptions;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.summer.campussct.mapper.VehiclePublishMapper;
import com.summer.campussct.pojo.*;
import com.summer.campussct.mapper.VehicleMapper;
import com.summer.campussct.pojo.dto.*;
import com.summer.campussct.service.*;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.summer.campussct.utils.FileUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.time.LocalDate;
import java.util.*;
import java.util.stream.Collectors;

/**
 * <p>
 *  服务实现类
 * </p>
 *
 * @author Mr.Chen
 * @since 2024-04-21
 */
@Service
@Slf4j
public class VehicleServiceImpl extends ServiceImpl<VehicleMapper, Vehicle> implements IVehicleService {

    @Resource
    private IVehicleMarketService vehicleMarketService;

    @Resource VehicleMapper vehicleMapper;

    @Resource
    private VehiclePublishMapper vehiclePublishMapper;

    @Resource
    private IVehicleAuditService vehicleAuditService;

    @Value("${file-position.vehiclePath}")
    private String vehiclePath;

    @Resource
    private FileUtil fileUtil;

    @Override
    @Transactional
    public RestResult addVehicle2(VehicleInfoDto vehicleInfoDto) {
        // 1. 添加vehicle表
        boolean saveVehicle = this.save(vehicleInfoDto);
        if (!saveVehicle){ throw new RuntimeException("添加vehicle表失败");}
        Long vid = vehicleInfoDto.getId();

        // 2. 添加vehicleMarket表
        VehicleMarket vehicleMarket = vehicleInfoDto.getVehicleMarket();
        vehicleMarket.setVid(vid);
        // 若没指定入库日期则为当前日期
        LocalDate comeDate = vehicleMarket.getComeDate();
        if (comeDate == null) {
            vehicleMarket.setComeDate(LocalDate.now());
        }
        // 将封面图片与详细图片转存，并重set vehicleMarket 中的相应值
        transferTempImages(vehicleMarket, vid);
        boolean saveVehicleMarket = vehicleMarketService.save(vehicleMarket);
        if (!saveVehicleMarket){ throw new RuntimeException("添加vehicleMarket表失败");}

        // 3. 添加vehicle_audit表
        VehicleAudit vehicleAudit = new VehicleAudit();
        vehicleAudit.setVid(vid);
        boolean isSuccessAudit = vehicleAuditService.save(vehicleAudit);
        if (!isSuccessAudit) throw new RuntimeException("添加vehicle_audit表失败");

        return RestResult.success();
    }

    @Override
    public RestResult getVehicleByUser(PublishQueryParams publishQueryParams) {
        List<VehicleInfoDto> list =  vehicleMapper.getVehicleByUser(publishQueryParams);
        return RestResult.success(list);
    }

    @Override
    public RestResult getAuditList() {
        List<VehicleInfoDto> auditList = vehicleMapper.getAuditList();
        return RestResult.success(auditList);
    }

    @Override
    @Transactional
    public RestResult modifyVehicle(VehicleInfoDto vehicleInfoDto) {
        long vid = vehicleInfoDto.getId();
        // 只有未发布的车辆才能修改
        VehicleAudit vehicleAudit = vehicleAuditService.getOne(new LambdaQueryWrapper<VehicleAudit>()
                .eq(VehicleAudit::getVid, vid));
        if (vehicleAudit.getPublishStatus() != 30001){
            throw new RuntimeException("已发布的车辆不能修改");
        }

        // 1. 修改vehicle表
        Vehicle vehicle = this.getById(vid);
        if (vehicle == null) throw new RuntimeException("更新vehicle表失败");
        // 将修改的属性copy到vehicle中
        BeanUtil.copyProperties(vehicleInfoDto, vehicle, CopyOptions.create().ignoreNullValue());
        boolean updateById = this.updateById(vehicle);
        if (!updateById) throw new RuntimeException("更新vehicle表失败");

        // 2. 修改vehicleMarket表
        // 2.1 如果修改了图片，则重新转存上传的照片，并删掉之前的图片
        VehicleMarket vehicleMarketUpload = vehicleInfoDto.getVehicleMarket();
        transferTempImages(vehicleMarketUpload, vid);
        String newFrontPic = vehicleMarketUpload.getFrontPic();
        String newMainPics = vehicleMarketUpload.getMainPictures();
        VehicleMarket vehicleMarket = vehicleMarketService.getOne(new LambdaQueryWrapper<VehicleMarket>()
                .eq(VehicleMarket::getVid, vid));
        if (vehicleMarket == null) throw new RuntimeException("更新vehicle_market表失败");
        String oldFrontPic = vehicleMarket.getFrontPic();
        String oldMainPics = vehicleMarket.getMainPictures();
        BeanUtil.copyProperties(vehicleMarketUpload, vehicleMarket, CopyOptions.create().ignoreNullValue());
        boolean updateById1 = vehicleMarketService.updateById(vehicleMarket);
        if (!updateById1) throw new RuntimeException("更新vehicle_market表失败");

        // 3. 修改audit表：修改过后改为待提交
        boolean update = vehicleAuditService.update(new LambdaUpdateWrapper<VehicleAudit>()
                .set(VehicleAudit::getAuditStatus, 20001)
                .eq(VehicleAudit::getVid, vid));
        if (!update) throw new RuntimeException("修改audit表失败");

        //4. 此时更新成功，删除旧照片
        try {
            if (!Objects.equals(oldFrontPic, newFrontPic)){
                fileUtil.deleteFile(oldFrontPic);
            }
            List<String> oldMainPicList = JSONUtil.toList(oldMainPics, String.class);
            List<String> newMainPicList = JSONUtil.toList(newMainPics, String.class);
            // 做差集运算：old集合-new集合，得到需要删除的图片集合
            List<String> deleteList = oldMainPicList.stream()
                    .filter(e -> !newMainPicList.contains(e))
                    .collect(Collectors.toList());
            for (String url : deleteList) {
                fileUtil.deleteFile(url);
            }
        } catch (IOException e) {
            throw new RuntimeException("删除照片失败");
        }
        return RestResult.success();
    }

    @Override
    @Transactional
    public RestResult deleteVehicle(long id) {
        // 发布后的车子需等到下架后才能删除
        VehiclePublish vehiclePublish = vehiclePublishMapper.selectOne(new LambdaQueryWrapper<VehiclePublish>()
                .select(VehiclePublish::getId, VehiclePublish::getPublishStatus)
                .eq(VehiclePublish::getVid, id));
        if (vehiclePublish != null){
            if(vehiclePublish.getPublishStatus() != 30004){
                throw new RuntimeException("未下架的车子不能删除");
            }
            // 删除vehicle_public表
            int b = vehiclePublishMapper.deleteById(vehiclePublish.getId());
            if (b == 0) throw new RuntimeException("删除publish失败");
        }

        // 1. 删除vehicle
        boolean removeVehicle = this.removeById(id);
        if (!removeVehicle) throw new RuntimeException("删除vehicle失败");
        // 2. 删除vehicle_market
        LambdaQueryWrapper<VehicleMarket> lqw = new LambdaQueryWrapper<VehicleMarket>();
                lqw.eq(VehicleMarket::getVid, id);
        VehicleMarket vehicleMarket = vehicleMarketService.getOne(lqw);

        boolean removeVehicleMarket = vehicleMarketService.remove(lqw);
        if (!removeVehicleMarket) throw new RuntimeException("删除VehicleMarket失败");
        // 3. 删除audit
        boolean removeAudit = vehicleAuditService.remove(new LambdaQueryWrapper<VehicleAudit>()
                .eq(VehicleAudit::getVid, id));
        if (!removeAudit) throw new RuntimeException("删除audit失败");

        // 4. 删除照片
        try {
            fileUtil.deleteFile(vehicleMarket.getFrontPic());
            for (String url : JSONUtil.toList(vehicleMarket.getMainPictures(), String.class)) {
                fileUtil.deleteFile(url);
            }
        } catch (IOException e) {
            log.error("删除照片失败");
            e.printStackTrace();
        }
        return RestResult.success();
    }

    @Override
    public RestResult browseVehicle(long id) {
        VehicleInfoDto vehicleInfoDto = vehicleMapper.getVehicleInfoById(id);
        return RestResult.success(vehicleInfoDto);
    }

    private void transferTempImages(VehicleMarket vehicleMarket, Long vid) {
        // 转存封面图片
        String frontPic = vehicleMarket.getFrontPic();
        // 如果url中不包含temp，说明没修改过照片,不进行转存
        if (frontPic.contains("temp")){
            String newUrl = fileUtil.transferSave(vid, frontPic, vehiclePath);
            vehicleMarket.setFrontPic(newUrl);
        }
        // 转存详细图片
        String mainPictures = vehicleMarket.getMainPictures();
        List<String> mainPicList = JSONUtil.toList(mainPictures, String.class);
        List<String> newMainPicList = new ArrayList<>();
        for (String url : mainPicList) {
            // 如果url中不包含temp，说明没修改过照片,不进行转存
            if (url.contains("temp")){
                newMainPicList.add(fileUtil.transferSave(vid, url, vehiclePath));
            } else {
                newMainPicList.add(url);
            }
        }
        vehicleMarket.setMainPictures(JSONUtil.toJsonStr(newMainPicList));
    }
}
